<template>
	<view class="kui-fixed kui-w-full kui-inset-l-0 kui-inset-r-0 kui-box-border"
		:class="[state.animationName, !state.full ? 'kui-py-8 kui-px-12' : '']" :style="{
		top: state.top,
		bottom: state.bottom
	}" v-show="show">
		<view class="kui-py-3 kui-w-full" :style="rootStyle">
			<slot>
				<view class="kui-h-full kui-flex kui-flex-col kui-justify-center kui-px-3"
					:class="[contentCenter ? 'kui-items-center' : '']">
					<view>
						<kui-text :color="state.color">{{ content }}</kui-text>
					</view>
					<view class="kui-w-full kui-flex kui-justify-end"
						:class="[($slots['action'] || actionSlot) ? 'kui-mt-3' : '']">
						<slot name="action"></slot>
					</view>
				</view>
			</slot>
		</view>
	</view>
</template>

<script lang="ts">
	import {
		defineComponent,
		reactive,
		getCurrentInstance,
		SetupContext,
		CSSProperties,
		computed,
		watch,
		useSlots,
		nextTick
	} from 'vue';

	import SnackbarProps from './props';

	const name = 'kui-snackbar';

	export default defineComponent({
		name,
		props: SnackbarProps,
		emits: ['update:show', 'closed'],
		setup(props, context: SetupContext) {
			let timer: null | any = null;

			const {
				proxy
			}: any = getCurrentInstance();
			const theme = proxy.$theme;

			const state = reactive({
				show: props.show,
				animationName: null,
				color: props.color,
				top: null,
				bottom: null,
				type: props.type,
				full: props.full,
				opacity: props.opacity
			});

			const rootStyle = computed(() => {
				const style: CSSProperties = reactive({});

				style.fontSize = `${theme.size.fonts.md}px`;
				state.type = theme.colors['light'][props.type] ? props.type : 'primary';
				style.backgroundColor = theme.colors['light'][state.type][5];

				if (props.backgroundColor) {
					style.backgroundColor = props.backgroundColor;
				} else {
					style.backgroundImage =
						`linear-gradient(to right, ${theme.colors['light'][state.type][5]}, ${theme.colors['light'][state.type][4]})`;
				}

				// 朴素类型
				if (props.plain) {
					style.backgroundImage = '';
					style.backgroundColor = theme.colors['light'][state.type][1];
					state.color = theme.colors['light'][state.type][5];
				}

				// 非通栏
				if (!state.full) {
					style.borderRadius = `10rpx`;
				}

				// 透明度
				if (state.opacity) {
					style.opacity = state.opacity;
				}

				return style;
			});

			const getAnimationName = (position: string, type: string) => {
				state.animationName = `slide-${type}-${position}`;
			}

			const getPosition = (position: string = 'top') => {
				// 自定义位置
				if (position === 'bottom') {
					state.bottom = `${props.bottom}px`;
					state.top = null;
				}
				if (position === 'top') {
					state.top = `${props.top}px`;
					state.bottom = null;
				}
			}

			const clearTimer = () => {
				if (timer) {
					clearTimeout(timer);
					timer = null;
				}
			}

			const hide = () => {
				getAnimationName(props.position, 'out');
				setTimeout(() => {
					context.emit('update:show', false);
					context.emit('closed');
					getAnimationName(props.position, 'in');
				}, 200);
			}

			const show = () => {
				clearTimer();
				getAnimationName(props.position, 'in');
				if (props.duration) {
					timer = setTimeout(() => {
						hide();
					}, props.duration);
				}
			}

			watch(
				() => [props.show, props.top, props.full, props.position],
				(newVal) => {
					if (newVal[0]) {
						show();
					}
					if (newVal[1]) {
						state.top = newVal[1];
					}
					state.full = newVal[2];
					getPosition(newVal[3]);
				}
			);

			return {
				rootStyle,
				state
			}
		}
	});
</script>

<style lang="less">
	.slide-in-top {
		-webkit-animation: slide-in-top .5s cubic-bezier(.25, .46, .45, .94) both;
		animation: slide-in-top .5s cubic-bezier(.25, .46, .45, .94) both
	}

	@-webkit-keyframes slide-in-top {
		0% {
			-webkit-transform: translateY(-1000px);
			transform: translateY(-1000px);
			opacity: 0
		}

		100% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}
	}

	@keyframes slide-in-top {
		0% {
			-webkit-transform: translateY(-1000px);
			transform: translateY(-1000px);
			opacity: 0
		}

		100% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}
	}

	.slide-out-top {
		-webkit-animation: slide-out-top .5s cubic-bezier(.55, .085, .68, .53) both;
		animation: slide-out-top .5s cubic-bezier(.55, .085, .68, .53) both
	}

	@-webkit-keyframes slide-out-top {
		0% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}

		100% {
			-webkit-transform: translateY(-1000px);
			transform: translateY(-1000px);
			opacity: 0
		}
	}

	@keyframes slide-out-top {
		0% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}

		100% {
			-webkit-transform: translateY(-1000px);
			transform: translateY(-1000px);
			opacity: 0
		}
	}

	.slide-in-bottom {
		-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) both;
		animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) both
	}

	@-webkit-keyframes slide-in-bottom {
		0% {
			-webkit-transform: translateY(1000px);
			transform: translateY(1000px);
			opacity: 0
		}

		100% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}
	}

	@keyframes slide-in-bottom {
		0% {
			-webkit-transform: translateY(1000px);
			transform: translateY(1000px);
			opacity: 0
		}

		100% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}
	}

	.slide-out-bottom {
		-webkit-animation: slide-out-bottom .5s cubic-bezier(.55, .085, .68, .53) both;
		animation: slide-out-bottom .5s cubic-bezier(.55, .085, .68, .53) both
	}

	@-webkit-keyframes slide-out-bottom {
		0% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}

		100% {
			-webkit-transform: translateY(1000px);
			transform: translateY(1000px);
			opacity: 0
		}
	}

	@keyframes slide-out-bottom {
		0% {
			-webkit-transform: translateY(0);
			transform: translateY(0);
			opacity: 1
		}

		100% {
			-webkit-transform: translateY(1000px);
			transform: translateY(1000px);
			opacity: 0
		}
	}
</style>
